package gotlib

import (
	"fmt"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/shopspring/decimal"
	"strings"
	"time"
)

//type TNumber interface {
//	int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 | string | interface{}
//}

//func ToDecimal[T TNumber](a T) (dec decimal.Decimal) {
//	dec, err := decimal.NewFromString(strings.ReplaceAll(fmt.Sprint(a), ",", ""))
//	if err != nil {
//		fmt.Println("ToDecimal 不能转换数据到decimal.Decimal类型。", a)
//		return
//	}
//	return dec
//}

func ToDecimal(a interface{}) (dec decimal.Decimal) {
	dec, err := decimal.NewFromString(strings.ReplaceAll(fmt.Sprint(a), ",", ""))
	if err != nil {
		fmt.Println("ToDecimal 不能转换数据到decimal.Decimal类型。", a)
		return
	}
	return dec
}

//func TCalculateString[T1 TNumber, T2 TNumber](operate string, a T1, b T2, digits ...int) (ret string) {
//	dec := TCalculate(operate, a, b)
//
//	if len(digits) == 0 {
//		return dec.String()
//	}
//	iDigits := int32(digits[0])
//	return dec.Round(iDigits).String()
//}

func CalculateString(operate string, a, b interface{}, digits ...int) (ret string) {
	dec := Calculate(operate, a, b)

	if len(digits) == 0 {
		return fmt.Sprint(dec)
	}
	iDigits := int32(digits[0])
	return decimal.NewFromFloat(dec).Round(iDigits).String()
}
func Calculate(operate string, a, b interface{}) (retFloat float64) {

	var a1, b1, ret decimal.Decimal
	a1 = ToDecimal(a)
	b1 = ToDecimal(b)

	switch operate {
	case "+", "add":
		ret = a1.Add(b1)
	case "-", "sub":
		ret = a1.Sub(b1)
	case "*", "mul":
		ret = a1.Mul(b1)
	case "/", "div":
		ret = a1.Div(b1)
	case "\\": //取整数部分
		ret = decimal.NewFromInt(a1.Div(b1).IntPart())
	case "%", "mod":
		ret = a1.Mod(b1)
	case "pow":
		ret = a1.Pow(b1)
	default:
		fmt.Println("Calculate function operate is incorrect.", operate, a, b)
		return
	}
	retFloat, _ = ret.Float64()
	return retFloat
}

// CalcString 计算+-*/\%pow, 支持+*pow三种预算符的多参数运算，返回string
func CalcString(operate string, digits int, num ...interface{}) (ret string) {
	dec := Calc(operate, num...)

	if digits < 0 {
		return fmt.Sprint(dec)
	}
	iDigits := int32(digits)
	return decimal.NewFromFloat(dec).Round(iDigits).String()
}

// Calc 计算+-*/\%pow, 支持+*pow三种预算符的多参数运算，返回float64
func Calc(operate string, num ...interface{}) (retFloat float64) {

	var ret decimal.Decimal
	iLen := len(num)
	var n []decimal.Decimal
	for i := 0; i < iLen; i++ {
		n = append(n, ToDecimal(num[i]))
	}

	switch operate {
	case "+", "add":
		ret = ToDecimal(0)
		for i := 0; i < iLen; i++ {
			ret = ret.Add(n[i])
		}
	case "-", "sub":
		if iLen != 2 {
			fmt.Println("func Calc sub params are wrong")
			return 0
		} else {
			ret = n[0].Sub(n[1])
		}
	case "*", "mul":
		ret = ToDecimal(1)
		for i := 0; i < iLen; i++ {
			ret = ret.Mul(n[i])
		}
	case "/", "div":
		if iLen != 2 {
			fmt.Println("func Calc div params are wrong")
			return 0
		} else {
			ret = n[0].Div(n[1])
		}
	case "\\": //取整数部分
		if iLen != 2 {
			fmt.Println("func Calc \\取整数部分 params are wrong")
			return 0
		} else {
			ret = decimal.NewFromInt(n[0].Div(n[1]).IntPart())
		}
	case "%", "mod":
		if iLen != 2 {
			fmt.Println("func Calc div params are wrong")
			return 0
		} else {
			ret = n[0].Mod(n[1])
		}
	case "pow":
		ret = n[0]
		for i := 1; i < iLen; i++ {
			ret = ret.Pow(n[i])
		}

	default:
		fmt.Println("Calculate function operate is incorrect.", operate, num)
		return
	}
	retFloat, _ = ret.Float64()
	return retFloat
}

// CalcTimeSub 两个时间相减
func CalcTimeSub(time1, time2 interface{}) (ret time.Duration) {
	var t1, t2 *gtime.Time
	t1 = gconv.GTime(time1)
	t2 = gconv.GTime(time2)
	return t1.Sub(t2)
}

// CalcTime 时间增加年月日时分秒
func CalcTime(time1 interface{}, y, m, d, h, n, s int) (time2 *gtime.Time) {
	t1 := gconv.GTime(time1)
	t1 = t1.AddDate(y, m, d)

	durationString := StrJoinAny("", h, "h", n, "m", s, "s")
	t1, _ = t1.AddStr(durationString)
	return t1
}

//func TCalculate[T1 TNumber, T2 TNumber](operate string, a T1, b T2) (ret decimal.Decimal) {
//
//	var a1, b1 decimal.Decimal
//	a1 = ToDecimal(a)
//	b1 = ToDecimal(b)
//
//	switch operate {
//	case "+", "add":
//		ret = a1.Add(b1)
//	case "-", "sub":
//		ret = a1.Sub(b1)
//	case "*", "mul":
//		ret = a1.Mul(b1)
//	case "/", "div":
//		ret = a1.Div(b1)
//	case "\\": //取整数部分
//		ret = decimal.NewFromInt(a1.Div(b1).IntPart())
//	case "%", "mod":
//		ret = a1.Mod(b1)
//	case "pow":
//		ret = a1.Pow(b1)
//	default:
//		fmt.Println("Calculate function operate is incorrect.", operate, a, b)
//		return
//	}
//	return ret
//}
